package com.game.share;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class StreamReader {
	final DataInputStream stream;

	private static final int BUFFER_SIZE = 1024;
	// 每个包最大尺寸： 64KB
	private static final int MAX_BUFFER = 1024 * 64;

	public StreamReader(InputStream input) {
		this.stream = new DataInputStream(input);
	}

	public int readInt() throws IOException {
		return stream.readInt();
	}
	
	public long readLong() throws IOException {
		return stream.readLong();
	}

	public String readString() throws IOException {
		int len = stream.readInt();
		if(len > MAX_BUFFER){
			throw new  IOException("out of memory read error : " + len );
		}
		byte[] data = new byte[len];
		int read = stream.read(data);
		if (read < len) {
			System.out.println("read error : " + len + "," + read);
			return "";
		}
		return Util.byteToString(data);
	}

	public IOPackage readPackage() throws IOException {
		int type = readInt();
		int len = readInt();
		byte[] data = readData(stream, len);
		return new IOPackage(IOPackage.getPackageType(type), data);
	}

	public void close() {
		try {
			stream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static byte[] ZERO_DATA = new byte[0];
	
	public byte[] readData(int len) throws IOException{
		return readData(stream, len);
	}

	private static byte[] readData(InputStream input, int len)
			throws IOException {
		if (len == 0) {
			return ZERO_DATA;
		}
		if (len <= BUFFER_SIZE) {
			byte[] tmp = new byte[len];
			input.read(tmp);
			return tmp;
		}
		if (MAX_BUFFER < len) {
			throw new IOException("data out of max size : " + len);
		}
		return readLargeData(input, len);
	}

	private static byte[] readLargeData(InputStream input, int len)
			throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream(len);
		int times = len / BUFFER_SIZE;
		byte[] tmp = new byte[BUFFER_SIZE];
		int count = 0;
		int totalCount = 0;

		for (int i = 0; i < times; i++) {
			count = input.read(tmp);
			out.write(tmp, 0, count);
			totalCount += count;
		}
		count = input.read(tmp, 0, len - totalCount);
		out.write(tmp, 0, count);
		totalCount += count;
		if (totalCount != len) {
			// @ TODO
			System.err.println("read buff failed");
		}
		return out.toByteArray();
	}

	public static void main(String[] args) throws Exception {
		test(0);
		test(1);
		test(1024);
		test(1023);
		test(1025);
		test(1024 * 8);
		test(1024 * 8 + 1);
		test(1024 * 8 - 1);
		test(1024 * 12);
	}

	private static void test(int len) throws Exception {
		FileInputStream in = new FileInputStream("gdb.pdf");
		byte[] data = readLargeData(in, len);
		System.out.println(len + " --> " + data.length);
		in.close();
	}

}
